/***************************************************************************
 *   Copyright (C) 2008 by András Bécsi                                    *
 *   andrewbecsi @ yahoo . co . uk                                         *
 *                                                                         *
 *   This source file is part of the Qtdict project.                       *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

#include "centralwidget.h"

InfoWidget::InfoWidget(QWidget *parent): QWidget(parent){
    qDebug() << "In function "+QString(Q_FUNC_INFO);
    setupUi(this);    
    icon = QPixmap(QString::fromUtf8(":/pic/qtdict.png"));
    iconLabel = new QLabel(this);
    iconLabel -> setPixmap(icon);
    gridLayout->addWidget(iconLabel, 0, 0, Qt::AlignCenter);
    showIcon();
}

void InfoWidget::showText(const QString &str){
    iconLabel->hide();
    infoBrowser -> setText(str);
    infoBrowser -> show();    
}

void InfoWidget::showIcon(){
    infoBrowser -> hide();
    iconLabel->show();
}

CentralWidget::CentralWidget(QWidget *parent): QWidget(parent) {
    QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));
    QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8"));
    qDebug() << "In function "+QString(Q_FUNC_INFO);
    setupUi(this);
    manager = new DictionaryPool(this);

    poolSelectionWidget = new SelectionWidget(manager->plugins(),this);
    machineInput=new QPlainTextEdit(this);
    machineInput->setAccessibleName(tr("Gépi fordítás"));
    machineInput->setPlainText(tr("Gépi fordítás a Google Translate webes szolgáltatása segítségével.\n"
                                  "Ide gépelje be a fordítani kívánt szöveget!"));
    machineInput->selectAll();
    gridLayout->addWidget(machineInput, 2, 0);    
    machineInput->hide();
    mTrans=false;
    mTransButton->hide();
//    configButton->hide();


    completer = new QCompleter(history, this);
    completer->setCaseSensitivity(Qt::CaseInsensitive);
    lineEdit->setCompleter(completer);
    lineEdit->setContextMenuPolicy(Qt::NoContextMenu);
    http=new QHttp(this);

    histCap=50;

    setInNewTab(false);

    crossButton = new QToolButton(this);
    crossButton->setIcon( QIcon(":/pic/tab_close.png") );
    crossButton->setShortcut(tr("Ctrl+W"));

    crossButton->setEnabled(false);
    tabWidget->setCornerWidget(crossButton);
    tabWidget->clear();
    setConnections();
    //manager->sync();
    manager->selectAll();
    newTab();
}


CentralWidget::~CentralWidget(){
    qDebug() << "In function "+QString(Q_FUNC_INFO);
    delete http;
    qDebug() << "http deleted";
    delete crossButton;
    qDebug() << "http deleted";
    delete completer;
    qDebug() << "comleter deleted";
    delete manager;
    qDebug() << "manager deleted";
}

int CentralWidget::tabCount(){
    return tabWidget->count();
}

void CentralWidget::setConnections(){
    qDebug() << "In function "+QString(Q_FUNC_INFO);

    connect(machineInput,SIGNAL(textChanged()),
            this, SLOT(slotMachineInputTextChanged()));
    connect(dicSelectButton, SIGNAL(clicked()),
            this, SLOT(showSelectionWidget()));
    connect(this, SIGNAL(machineInputChanged( const QString & )),
            this, SLOT(on_lineEdit_textEdited( const QString & )));    
    connect(this->pushButton, SIGNAL(clicked()),
            lineEdit, SLOT(selectAll()));
    connect(this->http, SIGNAL(requestFinished(int, bool)),
            this, SLOT(httpRequestFinished(int, bool)));
    connect(this->http, SIGNAL(done(bool)),
            this, SLOT(finished(bool)));
    connect(this->crossButton, SIGNAL(clicked()),
            this, SLOT(slotCloseCurrentTab()));
    connect(this->fromBox, SIGNAL( currentIndexChanged(const QString&) ),
            this, SLOT( refreshToBox(const QString&) ) );
    connect(manager, SIGNAL(errorOccured( const QString & )),
            this, SLOT( handleErrors( const QString & ) ) );
    connect(manager, SIGNAL(refreshRequest( const LangHash & )),
            this, SLOT( refreshLangBox( const LangHash & ) ) );
    connect(manager, SIGNAL( refreshRequest( const DicHash*  ) ),
            poolSelectionWidget, SLOT( refresh(  const DicHash*  ) ) );
    connect(manager, SIGNAL(tabAdditionRequest(DataModel *, const QString &)),
            this, SLOT( addTab(DataModel *, const QString & ) ) );
    connect(poolSelectionWidget, SIGNAL(refreshRequest()),
            manager, SLOT(refreshPlugins()));
    connect(poolSelectionWidget, SIGNAL(configRequest( const QHash< QByteArray, bool>& )),
            manager, SLOT(config( const QHash< QByteArray, bool>& )));
}

void CentralWidget::setTray(DictionaryTray *ticon){
    qDebug() << "In function "+QString(Q_FUNC_INFO);
    tray=ticon;
}

bool CentralWidget::setInNewTab(bool option){
    qDebug() << "In function "+QString(Q_FUNC_INFO);
        tabOption=option;
        return tabOption;
}

void CentralWidget::slotCloseCurrentTab(){
   qDebug() << "In function "+QString(Q_FUNC_INFO);
   removeTab(tabWidget->currentIndex());
   if (tabWidget->count() == 0) newTab();
   if (tabWidget->count() == 1 &&
       tabWidget->currentWidget()->accessibleName() == tr("[Új Lap]"))
       crossButton->setEnabled(false);
}

void CentralWidget::httpRequestFinished(int requestId, bool error){
    qDebug() << "In function "+QString(Q_FUNC_INFO);
    if (error) {
        qDebug() << "ERROR in function "+QString(Q_FUNC_INFO);
        qDebug() << "Error maybe in "+http->currentRequest ().values().last().second+" ?";
        qDebug() << "No connection: "+http->currentRequest().values().last().second;
        site = QString ("<font color=\"red\">"+tr("A csatlakozás nem sikerült: ")
                        +http->currentRequest().values().last().second);
        return;
    }
    if ( requestId == request ) {
        data->close();
        site = QString(data->data());
    }
}

void CentralWidget::finished(bool error){
    qDebug() << "In function "+QString(Q_FUNC_INFO);
    QTextBrowser *browser = new QTextBrowser(this);
    browser->setReadOnly(true);
    browser->acceptRichText();
    browser->setAccessibleName(tr("Böngésző"));
    QRegExp rx("<a href(.*)</a>");
    rx.setMinimal(true);
    site=site.remove(rx);
   /* rx=QRegExp("<div id=\"navigation\">(.*)</div>");
    rx.setMinimal(true);
    site=site.remove(rx);*/
    if (error) {
        qDebug() << "ERROR in function "+QString(Q_FUNC_INFO);
        browser->setText("<center>"+tr("Hiba történt!")+"<br/><br/>"+site);

        if (site.isNull()) browser->setText("<center><font color=\"red\"><br/><br/>"+tr("A kért oldal nem elérhető!")+"<br/>"
                                            +http->currentRequest().values().last().second);
    }else browser->setText(site);
    
    addTab(browser,tabOption);
    crossButton->setEnabled(true);
    http->abort();
}

int CentralWidget::addTab(DataModel *model, const QString &word){
    qDebug() << "In function "+QString(Q_FUNC_INFO);
    lineEdit->setFocus();
    QTreeView *view = new QTreeView(this);
    QFile file(":/qss/treeview.qss");
    file.open(QFile::ReadOnly);
    QString styleSheet = QLatin1String(file.readAll());

    currentModel=model;

    //view->setStyleSheet(styleSheet);
    view->resizeColumnToContents(0);
    view->header()->setResizeMode(QHeaderView::ResizeToContents);
    view->setModel(model);
    view->setDragEnabled(true);
    view->setAccessibleName(word);
    view->expandAll();
    view->setAlternatingRowColors ( true );
    view->setWordWrap(true);
    connect(view,SIGNAL(activated ( const QModelIndex & )),
            this,SLOT(handleDoubleClick ( const QModelIndex & )));
    //
    //tabWidget->clear();
    //
    return addTab(view, tabOption, word);
}

//the bool flag argument forces the opening into a new tab
int CentralWidget::addTab(QWidget *widget, bool option, const QString &title, bool flag){
    qDebug() << "In function "+QString(Q_FUNC_INFO);
    if(!mTrans){
        int index=-1;
        if( !option || ( ( tabWidget->count()!=0 && tabWidget->currentWidget()->accessibleName()==tr("[Új Lap]")) && !flag ) ){
            qDebug() << "In function "+QString(Q_FUNC_INFO)+": REMOVE_TAB";
            index=tabWidget->currentIndex();
            removeTab(index);
        }
        QString name=( widget->accessibleName().isEmpty() ||
                       widget->accessibleName() == tr(""))?title:widget->accessibleName();

        tabWidget->insertTab(index,widget,name);
        index=indexOf(widget);
        tabWidget->setCurrentIndex(index);

        if( tabWidget->count()>1 ) crossButton->setEnabled(true);

        qDebug("Tab added.");
        return tabWidget->currentIndex();
    }else return -1;
}

void CentralWidget::removeTab(int idx){
    qDebug() << "In function "+QString(Q_FUNC_INFO)<<" idx="<<idx;

    QWidget *tmp = tabWidget->widget(idx);
    tabWidget->removeTab(idx);

    if ( tmp == poolSelectionWidget ){
        dicSelectButton->setEnabled(true);
        dicSelectButton->setChecked(false);
    }

    if ( tmp == machineInput){
        lineEdit->setEnabled(true);
        lineEdit->setFocus();
        mTransButton->setChecked(false);
        mTrans=false;
    }
    if ( tmp != poolSelectionWidget && tmp != machineInput ) delete tmp;
}

int CentralWidget::indexOf(QWidget *widget){
    return tabWidget->indexOf(widget);
}

void CentralWidget::setCurrentIndex(int idx){
    tabWidget->setCurrentIndex(idx);
}

void CentralWidget::showLicence(){
    qDebug() << "licence: In function "+QString(Q_FUNC_INFO);
    if (ONLINE) {        
        //	http://www.gnu.hu/gpl.html
        http->setHost(tr("www.gnu.hu"));
        data = new QBuffer(this);
        request=http->get(tr("/gpl.html"), data);
    }else{
        QMessageBox::information(this,tr("Információ"),tr("Offline mód\nutils.h:\n #define ONLINE false"));
    }
}

//!	show information in the tableWidget area
void CentralWidget::showInformation(const QString &info, const QString &title) {

    qDebug() << "In function "+QString(Q_FUNC_INFO);    
    QString text = info;
    InfoWidget* iWidget = new InfoWidget(this);
    iWidget->showText(info);
    iWidget->setAccessibleName( title );
    addTab(iWidget,tabOption);

}

void CentralWidget::newTab(){

        qDebug() << "In function "+QString(Q_FUNC_INFO);
        InfoWidget* iWidget = new InfoWidget(this);
        iWidget->showIcon();
        iWidget->setAccessibleName(tr("[Új Lap]"));
        //the last bool argument of addTab forces the opening into a new tab
        addTab(iWidget, true, tr("[Új Lap]"), true);

}

LangPair CentralWidget::currentLangPair(){    
    return qMakePair( lngConv.str2Lang(fromBox->currentText()), lngConv.str2Lang(toBox->currentText()) );
}

void CentralWidget::setCurrentLangPair( const QString &from, const QString &to){
    bool error=false;
    int fIdx=fromBox->findText( from );
    int tIdx;

    if (fIdx!=-1){
        fromBox->setCurrentIndex( fIdx );
        tIdx=toBox->findText( to );
        if (tIdx!=-1){
            toBox->setCurrentIndex( tIdx );
        }else error=true;
    } else error=true;

    if (error)
        handleErrors(tr("Nincs ilyen szótár!"));
}

void CentralWidget::refreshLangBox(const LangHash &langHash){
    qDebug() << "In function "+QString(Q_FUNC_INFO);
    languages.clear();
    fromBox->clear();
    toBox->clear();
    foreach( LangPair lPair, langHash.keys() ){
        languages.add( lngConv.lang2Str(lPair.first), lngConv.lang2Str(lPair.second) );
    }
    QStringList items = languages.keys();
    items.sort();
    fromBox->addItems(items);
    if (fromBox->count() == 0) fromBox->addItem(tr("[Forrásnyelv]"));
}

void CentralWidget::refreshToBox(const QString &text){
    qDebug() << "In function "+QString(Q_FUNC_INFO);
    QStringList items=languages.value(text);    
    items.sort();
    qDebug() << "ITEMS_SIZE: " << items.size();
    qDebug() << "ITEMS: " << items;
    toBox->clear();
    toBox->addItems(items);
    if (toBox->count() == 0) toBox->addItem(tr("[Célnyelv]"));
}

void CentralWidget::saveState(){
    qDebug() << "In function "+QString(Q_FUNC_INFO);
    if (history.size()>histCap) {
        history.removeLast();
    }
    if ( ! history.contains( currentState.word ) ){
        emit enableHistoryClearing(true);
        history << currentState.word;
        completer = new QCompleter(history, this);
        completer->setCaseSensitivity(Qt::CaseInsensitive);
        lineEdit->setCompleter(completer);
    }

#warning "maybe save the state somehow?"
}

void CentralWidget::on_switchButton_clicked(){
    setCurrentLangPair( toBox->currentText() , fromBox->currentText() );
}

void CentralWidget::on_lineEdit_textEdited( const QString &text ){
    pushButton->setEnabled(!text.isEmpty());
}

void CentralWidget::on_pushButton_clicked(){
    qDebug() << "In function "+QString(Q_FUNC_INFO);
    if(mTrans){
        QString word(machineInput->toPlainText());



    }else{
        QString word(lineEdit->text());
        currentState=State(word, currentLangPair(),modeBox->currentIndex());
        saveState( );
        emit enableHistoryClearing( !history.isEmpty() );
        emit information(tr("Letöltés folyamatban!"),
                         QString( fromBox->currentText() + " - " + toBox -> currentText() ),
                         word
                         );
        manager->collect(currentState);
    }
}

void CentralWidget::clearHistory(){
    history.clear();
    completer = new QCompleter(history, this);
    completer->setCaseSensitivity(Qt::CaseInsensitive);
    lineEdit->setCompleter(completer);
    emit enableHistoryClearing(false);
}

void CentralWidget::handleErrors(const QString &mess){
    #warning "TODO: implement error handling"
    qDebug() << "In function "+QString(Q_FUNC_INFO);
    if (!tray) QMessageBox::critical(this,"Hiba!", mess);
    else tray->showMessage("Hiba!", mess, QSystemTrayIcon::Critical);
    qWarning( qPrintable(mess) );
}

void CentralWidget::showSelectionWidget(){
    qDebug() << "In function "+QString(Q_FUNC_INFO);
    
    if (!mTrans){
        dicSelectButton->setDisabled(true);
        poolSelectionWidget->setup(manager->getCurrentSelections());
        int index=indexOf(poolSelectionWidget);
        if (index==-1){
            addTab(poolSelectionWidget, true);
            crossButton->setEnabled(true);
        }
        else setCurrentIndex(index);
        poolSelectionWidget->show();
    }else dicSelectButton->setChecked(false);
}

void CentralWidget::on_mTransButton_clicked(){
    qDebug() << "In function "+QString(Q_FUNC_INFO);    
    if(mTrans){
        lineEdit->setEnabled(true);
        pushButton->setEnabled(!lineEdit->text().isEmpty());
        lineEdit->setFocus();
        machineInput->hide();
        tabWidget->show();
    }else{
        tabWidget->hide();
        machineInput->show();
        lineEdit->setEnabled(false);
        machineInput->setFocus();
    }
    mTrans = mTransButton->isChecked();
}

void CentralWidget::slotMachineInputTextChanged(){
    qDebug() << "In function "+QString(Q_FUNC_INFO);
    QString tmp=machineInput->toPlainText();
    tmp.remove("\n");
    tmp.remove(" ");
    if (!tmp.isEmpty()) emit machineInputChanged(machineInput->toPlainText());
    else machineInputChanged(tmp);
}

void CentralWidget::handleDoubleClick ( const QModelIndex &index){
    QString clicked=currentModel->data(index).toString();
    lineEdit->setText(clicked);    
    pushButton->animateClick();
}
